#pragma once

#include "liblegerber_global.h"

#include <QObject>

#include "gerber.h"
#include "aperturetemplate.h"
#include "object.h"

namespace LeGerber
{

	class Command;

	// Rename to GerberEngine? Move some logic in commands?
	// FIXME: To avoid circle artifacts, always use 1 as the precision set with FS
	//  And calculate the rendering zoom factor FSLAX24Y24 => 10^4

	// TODO: See p26&27 for graphics state parameters and operation codes
	// See as well p59
	// TODO When using D01/2 with G02 and G03, G74/5 should have been called
	class LEGERBER_EXPORT Processor : public QObject
	{
		Q_OBJECT
	public:
		explicit Processor(QObject *parent = 0);
		~Processor();

		void setInterpolation(Interpolation interpolation);
		void setQuadrant(Quadrant quadrant);
		void setUnit(Unit unit);
		void setPolarity(Polarity polarity);

		bool addCustomApertureTemplate(CustomApertureTemplate *customTemplate);
		bool addAperture(int number, const QString &templateName, const QList<qreal> &templateParameters);
		void addComment(const QString &text);

		void beginRegion();
		void endRegion();
		void endSession();

		bool setAperture(quint32 number);
		bool stroke(const QPointF &to, const QPointF &distance = QPointF());
		bool moveTo(const QPointF &pos);
		bool flash(const QPointF &pos);

		QList<Object *> takeObjects();

		bool isError() const;
		QString errorMessage() const;
		int warningMessageCount() const;
		QStringList warningMessages() const;

	private:
		void error(const QString &text);
		QString m_errorMessage;
		void warning(const QString &text);
		QStringList m_warningMessages;

		ApertureTemplateDictionary m_apertureTemplateDictionary;
		ApertureDictionary m_apertureDictionary;
		Unit m_unit = InvalidUnit;
		Interpolation m_interpolation = InvalidInterpolation;
		Polarity m_polarity = DarkPolarity;
		Quadrant m_quadrant = InvalidQuadrant;
		Aperture *m_currentAperture = nullptr;
		QPointF m_currentPosition;
		QList<Object*> m_objects;
		bool m_inRegion = false;
		QPainterPath m_currentRegion;
		QList<QPainterPath> m_regions;
		QPointF mergeCoordinates(const QPointF &newPos, const QPointF &previousPos);
		QPainterPath strokePath(const QPainterPath &path);
		QPainterPath arcFromStartEndDistance(const QPointF &start, const QPointF &end, const QPointF &distance);
	};

}